package com.ywx.yypicturebackend.service.impl;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ywx.yypicturebackend.exception.BusinessException;
import com.ywx.yypicturebackend.exception.ErrorCode;
import com.ywx.yypicturebackend.exception.ThrowUtils;
import com.ywx.yypicturebackend.mapper.SpaceMapper;
import com.ywx.yypicturebackend.model.dto.space.analyze.*;
import com.ywx.yypicturebackend.model.entity.Picture;
import com.ywx.yypicturebackend.model.entity.Space;
import com.ywx.yypicturebackend.model.entity.User;
import com.ywx.yypicturebackend.model.vo.space.analyze.*;
import com.ywx.yypicturebackend.service.PictureService;
import com.ywx.yypicturebackend.service.SpaceAnalyzeService;
import com.ywx.yypicturebackend.service.SpaceService;
import com.ywx.yypicturebackend.service.UserService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static cn.hutool.http.ContentType.JSON;

@Service
public class SpaceAnalyzeServiceImpl extends ServiceImpl<SpaceMapper, Space> implements SpaceAnalyzeService {

    @Resource
    UserService userService;

    @Resource
    SpaceService spaceService;

    @Resource
    PictureService pictureService;


    @Override
    public SpaceUsageAnalyzeResponse getSpaceUsageAnalyze(SpaceUsageAnalyzeRequest spaceUsageAnalyzeRequest, User loginUser) {
        //校验参数
        ThrowUtils.throwIf(spaceUsageAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
        //校验权限
        checkSpaceAuth(spaceUsageAnalyzeRequest, loginUser);

        //资源统计

        //公共空间或所有空间
        if (spaceUsageAnalyzeRequest.isQueryAll() || spaceUsageAnalyzeRequest.isQueryPublic()) {
            QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
            fillAnalyzeQueryWrapper(spaceUsageAnalyzeRequest, queryWrapper);
            queryWrapper.select("picSize");

            if (spaceUsageAnalyzeRequest.isQueryPublic()) {
                //如果是查询公共图库则需要spaceId为空
                queryWrapper.isNull("spaceId");
            }

            List<Object> pictureObjList = pictureService.getBaseMapper().selectObjs(queryWrapper);

            long sum = pictureObjList.stream()
                    .mapToLong(obj -> obj instanceof Number ? ((Long) obj) : 0).sum();

            //封装返回结果
            SpaceUsageAnalyzeResponse spaceUsageAnalyzeResponse = new SpaceUsageAnalyzeResponse();

            //公共图库没有上限设置,也没有比例
            spaceUsageAnalyzeResponse.setUsedSize(sum);
            spaceUsageAnalyzeResponse.setMaxSize(null);
            spaceUsageAnalyzeResponse.setSizeUsageRatio(null);
            spaceUsageAnalyzeResponse.setUsedCount((long) pictureObjList.size());
            spaceUsageAnalyzeResponse.setMaxCount(null);
            spaceUsageAnalyzeResponse.setCountUsageRatio(null);

            return spaceUsageAnalyzeResponse;
        } else {
            //私有空间
            Long spaceId = spaceUsageAnalyzeRequest.getSpaceId();
            ThrowUtils.throwIf(spaceId == null || spaceId <= 0, ErrorCode.PARAMS_ERROR, "空间id不能为空");
            Space space = spaceService.getById(spaceId);
            ThrowUtils.throwIf(space == null, ErrorCode.NOT_FOUND_ERROR, "空间不存在");

            //封装返回结果
            SpaceUsageAnalyzeResponse spaceUsageAnalyzeResponse = new SpaceUsageAnalyzeResponse();

            spaceUsageAnalyzeResponse.setUsedSize(space.getTotalSize());
            spaceUsageAnalyzeResponse.setMaxSize(space.getMaxSize());
            double sizeUsageRatio = NumberUtil.round(space.getTotalSize() * 100.0 / space.getMaxSize(), 2).doubleValue();
            spaceUsageAnalyzeResponse.setSizeUsageRatio(sizeUsageRatio);
            spaceUsageAnalyzeResponse.setUsedCount(space.getTotalCount());
            spaceUsageAnalyzeResponse.setMaxCount(space.getMaxCount());
            double countUsageRatio = NumberUtil.round(space.getTotalCount() * 100.0 / space.getMaxCount(), 2).doubleValue();

            spaceUsageAnalyzeResponse.setCountUsageRatio(countUsageRatio);

            return spaceUsageAnalyzeResponse;
        }

    }

    @Override
    public List<SpaceCategoryAnalyzeResponse> getSpaceCategoryAnalyze(SpaceCategoryAnalyzeRequest spaceCategoryAnalyzeRequest, User loginUser) {
        //校验参数
        ThrowUtils.throwIf(spaceCategoryAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
        //检查权限
        checkSpaceAuth(spaceCategoryAnalyzeRequest, loginUser);
        //补充查询范围
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        fillAnalyzeQueryWrapper(spaceCategoryAnalyzeRequest, queryWrapper);
        //使用mybatisplus查询
        queryWrapper.select("category",
                        "COUNT(*) as count",
                        "SUM(picSize) as totalSize")
                .groupBy("category");

        //查询并转换结果
        List<SpaceCategoryAnalyzeResponse> spaceCategoryAnalyzeResponses = pictureService.getBaseMapper().selectMaps(queryWrapper)
                .stream()
                .map(map -> {
                    String category = (String) map.get("category") != null ? map.get("category").toString() : "未分类";
                    Long count = ((Number) map.get("count")).longValue();
                    Long totalSize = ((Number) map.get("totalSize")).longValue();
                    return new SpaceCategoryAnalyzeResponse(category, count, totalSize);
                }).collect(Collectors.toList());


        return spaceCategoryAnalyzeResponses;
    }

    @Override
    public List<SpaceTagAnalyzeResponse> getSpaceTagAnalyze(SpaceTagAnalyzeRequest spaceTagAnalyzeRequest, User loginUser) {
        //校验参数
        ThrowUtils.throwIf(spaceTagAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
        //校验权限
        checkSpaceAuth(spaceTagAnalyzeRequest, loginUser);
        //构造查询参数
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        //填充查询范围
        fillAnalyzeQueryWrapper(spaceTagAnalyzeRequest, queryWrapper);

        //使用mybatis-plus查询标签
        queryWrapper.select("tags");
        List<Object> tagsObjList = pictureService.getBaseMapper().selectObjs(queryWrapper);

        List<String> stringList = tagsObjList.stream().filter(ObjectUtil::isNotNull)
                .map(Object::toString).collect(Collectors.toList());

        Map<String, Long> stringLongMap = stringList.stream().flatMap(tags -> {
            return JSONUtil.toList(tags, String.class).stream();//flatMap->将所有的流合并成一个流
        }).collect(Collectors.groupingBy(tag -> tag, Collectors.counting()));//tag -> tag：按标签本身分组（例如所有 "apple" 分到同一组）
        //Collectors.counting()：统计每组的元素数量


        //转换结果,并按使用次数降序排序排序
        return stringLongMap.entrySet().stream()
                .sorted((entry1, entry2) -> Long.compare(entry2.getValue(), entry1.getValue()))
                .map(entry -> new SpaceTagAnalyzeResponse(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());
    }

    @Override
    public List<SpaceSizeAnalyzeResponse> getSpaceSizeAnalyze(SpaceSizeAnalyzeRequest spaceSizeAnalyzeRequest, User loginUser) {
        //校验参数
        ThrowUtils.throwIf(spaceSizeAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
        //检查权限
        checkSpaceAuth(spaceSizeAnalyzeRequest, loginUser);

        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        //填充查询范围
        fillAnalyzeQueryWrapper(spaceSizeAnalyzeRequest, queryWrapper);
        queryWrapper.select("picSize");
        List<Long> sizeList = pictureService.getBaseMapper().selectObjs(queryWrapper).stream()
                .map(obj -> (Long) obj).collect(Collectors.toList());


        // 预定义分段阈值和对应的键（保持顺序）
        long[] thresholds = {
                100 * 1024,          // <100KB 上限
                500 * 1024,          // 100KB-500KB 上限
                1024 * 1024      // 500KB-1MB 上限
        };
        String[] rangeKeys = {
                "<100KB",
                "100KB-500KB",
                "500KB-1MB",
                ">1MB"                // 最后一个区间无上限
        };

        // 初始化计数器数组
        long[] counters = new long[rangeKeys.length];

        // 单次遍历统计所有区间
        for (long size : sizeList) {
            int index = 0;
            // 按顺序匹配区间
            while (index < thresholds.length && size >= thresholds[index]) {
                index++;
            }
            counters[index]++;
        }

        //构建结果集
        List<SpaceSizeAnalyzeResponse> spaceSizeAnalyzeResponses = new ArrayList<>();
        for (int i = 0; i < counters.length; i++) {
            spaceSizeAnalyzeResponses.add(new SpaceSizeAnalyzeResponse(rangeKeys[i], counters[i]));
        }


        return spaceSizeAnalyzeResponses;
    }

    @Override
    public List<SpaceUserAnalyzeResponse> getSpaceUserAnalyze(SpaceUserAnalyzeRequest spaceUserAnalyzeRequest, User loginUser) {
        ThrowUtils.throwIf(spaceUserAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);

        //构造查询条件
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        Long userId = spaceUserAnalyzeRequest.getUserId();
        queryWrapper.eq(ObjectUtil.isNotEmpty(userId), "userId", userId);
        fillAnalyzeQueryWrapper(spaceUserAnalyzeRequest, queryWrapper);

        //分析维度:每日,每周,每月
        String timeDimension = spaceUserAnalyzeRequest.getTimeDimension();
        switch (timeDimension) {
            case "day":
                queryWrapper.select("DATE_FORMAT(createTime, '%Y-%m-%d') AS period", "COUNT(*) AS count");
                break;
            case "week":
                queryWrapper.select("YEARWEEK(createTime) AS period", "COUNT(*) AS count");
                break;
            case "month":
                queryWrapper.select("DATE_FORMAT(createTime, '%Y-%m') AS period", "COUNT(*) AS count");
                break;
            default:
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "不支持的时间维度");
        }

        //分组和排序
        queryWrapper.groupBy("period").orderByAsc("period");

        return pictureService.getBaseMapper().selectMaps(queryWrapper)//以查询的字段为key，将结果映射为Map
                .stream().map(map -> {
                    return new SpaceUserAnalyzeResponse(map.get("period").toString(), Long.parseLong(map.get("count").toString()));
                }).collect(Collectors.toList());

    }

    @Override
    public List<Space> getSpaceRankAnalyze(SpaceRankAnalyzeRequest spaceRankAnalyzeRequest, User loginUser) {
        ThrowUtils.throwIf(spaceRankAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);

        QueryWrapper<Space> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id", "spaceName", "userId", "totalSize")
                .orderByDesc("totalSize")
                .last("LIMIT " + spaceRankAnalyzeRequest.getTopN()); // 取前 N 名

        // 查询结果
        return spaceService.list(queryWrapper);

    }


    /**
     * 校验分析空间权限
     *
     * @param spaceAnalyzeRequest
     * @param loginUser
     */
    private void checkSpaceAuth(SpaceAnalyzeRequest spaceAnalyzeRequest, User loginUser) {
        boolean queryPublic = spaceAnalyzeRequest.isQueryPublic();
        boolean queryAll = spaceAnalyzeRequest.isQueryAll();

        //检查权限
        if (queryPublic || queryAll) {
            //仅管理员可以分析所有空间或公共空间
            ThrowUtils.throwIf(!userService.isAdmin(loginUser), ErrorCode.NO_AUTH_ERROR);
        } else {
            //私有空间权限校验
            Long spaceId = spaceAnalyzeRequest.getSpaceId();
            ThrowUtils.throwIf(spaceId == null || spaceId <= 0, ErrorCode.PARAMS_ERROR, "空间id不能为空");
            Space space = spaceService.getById(spaceId);
            ThrowUtils.throwIf(space == null, ErrorCode.NOT_FOUND_ERROR, "空间不存在");
            spaceService.checkSpaceAuth(space, loginUser);
        }


    }


    /**
     * 根据分析范围填充查询条件
     *
     * @param spaceAnalyzeRequest
     * @param queryWrapper
     */
    private void fillAnalyzeQueryWrapper(SpaceAnalyzeRequest spaceAnalyzeRequest, QueryWrapper<Picture> queryWrapper) {

        if (spaceAnalyzeRequest.isQueryAll()) {
            return;
        }
        boolean queryPublic = spaceAnalyzeRequest.isQueryPublic();
        if (queryPublic) {
            queryWrapper.isNull("spaceId");
            return;
        }
        Long spaceId = spaceAnalyzeRequest.getSpaceId();
        if (spaceId != null) {
            queryWrapper.eq("spaceId", spaceId);
            return;
        }

        throw new BusinessException(ErrorCode.PARAMS_ERROR, "未指定分析范围");
    }


}
